#include <stdio.h>

#include <evalsoc.h>
#include "echeck.h"
#include "CRC_16_modbus.h"

#define PCLKFREQ                (50 * 1000000)
#define BAUD_RATE(n)            (PCLKFREQ / (n) / 16)

#define MODBUS_READ_FAIL -1
#define MODBUS_OUT_OF_RANGE -2
#define MODBUS_CRC_ERROR -3

int32_t uart485_write( dw_uart_regs_t * puart, uint8_t val )
{
    if (__RARELY(puart == NULL)) {
        return -1;
    }
    
    while ( (puart->LSR & 0x20) == 0 ) {
        __NOP();
    }
    
    /**/
    puart->THR = (uint32_t)val;

    
    return 0;
}
uint8_t uart485_read( dw_uart_regs_t * puart )
{

    uint16_t i=0;
    if (__RARELY(puart == NULL)) {
        return -1;
    }

    /**/
    while ( (puart->LSR & 0x1) == 0 ) {
        __NOP();
        i++;
        if(i>10000){
            return 101;
        }
    }

    return (uint8_t)( puart->RBR );
}

/**
 *  @brief modbusread
 *  @param command 读写指令
 *  @param addr 设备地址
 *  @param reg_num 寄存器地址
 *  @return 返回寄存器值
 */
//发送读取指令
uint32_t modbus_read(uint8_t command,uint8_t addr,uint8_t reg_num ){
    
    uint8_t recv_data[8];
    uint16_t i = 0;
    uint8_t data[] = {0x01,command,0x00,addr,0x00,reg_num}; //01 04 00 00 00 02
    uint8_t length = sizeof(data) / sizeof(data[0]);
    uint16_t crc_check = CRC_Check(data, length);

    for(int i=0;i<length;i++){
        uart485_write(UART1,data[i]);
    }
    uart485_write(UART1,crc_check>>8);
    uart485_write(UART1,crc_check&0xff);
    
    for (i = 0; i < 9; i++) {
        recv_data[i] = uart485_read(UART1);
        if (recv_data[i] == 101) {
            printf("modbus_read fail\r\n");
            return MODBUS_READ_FAIL;
        }
    }

    if(recv_data[5] ==0 && recv_data[6] == 0){
        printf("超出量程\r\n");
        return  MODBUS_OUT_OF_RANGE;

    }

    uint16_t crc_recv = (recv_data[7]<<8) | recv_data[8];
    uint16_t crc_calc = CRC_Check(recv_data, 7);

    if(crc_recv == crc_calc){
        printf("modbus_read success\r\n");
        return (recv_data[5]<<8) | recv_data[6];
    }else{
        printf("crc_check  fail\r\n");
        return MODBUS_CRC_ERROR;
    }
}



